<template>
  <div id="cesiumContainer"></div>
</template>
 
<script setup>
import * as Cesium from "cesium";
import { onMounted } from "vue";
onMounted(() => {
  // 引入服务器提供的图像
  var custom = new Cesium.ArcGisMapServerImageryProvider({
    url: "//services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
  });

  //自定义的配置内容
  var viewer = new Cesium.Viewer("cesiumContainer", {
    //配置是否创建baseLayerPicker小部件
    // baseLayerPicker:false,
    //配置图像的提供
    imageryProvider: custom,
    //配置Cesium的世界地形
    terrainProvider: Cesium.createWorldTerrain({
      //配置地形的3D效果
      requestWaterMask: true,
      requestVertexNormals: true,
    }),
  });


  //利用三维坐标来设置摄像头位置
  viewer.camera.setView({
    //设置摄像头初始的具体位置()
    destination: new Cesium.Cartesian3(1332761, -4662399, 4137888),
    //方向、视角角度的配置(可以直接用0-1进行设置)
    orientation: {
      heading: 0.6,
      pitch: -0.66,
    },
  });

  //引入Cesium官方自带的模型（引入自定义的模型需要注意格式）
  var city = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
      url: Cesium.IonResource.fromAssetId(3839),
    })
  );

  //定义3d样式（通过高度不同来设置不同的颜色）
  var heightStyle = new Cesium.Cesium3DTileStyle({
    color: {
      //条件判断（[条件,配置]）
      conditions: [
        ["${height} >= 300", "rgba(255,0,0,0.5)"],
        ["${height} >= 200", "rgb(255,165,0)"],
        ["${height} >= 100", "rgb(255,255,0)"],
        ["${height} >= 50", "rgb(0,255,0)"],
        ["${height} >= 25", "rgb(0,127,255)"],
        ["${height} >= 10", "rgb(0,0,255)"],
        ["${height} >= 5", "rgb(139,0,255)"],
        //true表示只要这个模型有,就改变它的颜色
        ["true", "rgb(127,59,8)"],
      ],
    },
  });

  //将定义好的样式赋值给引入的模型
  city.style = heightStyle;

  var geojsonOptions = {
    clampToGround: true,
  };

  // 从 GeoJson 文件加载邻域边界
  // Data from : https://data.cityofnewyork.us/City-Government/Neighborhood-Tabulation-Areas/cpf4-rkhq
  //GeoJSON是一种对各种地理数据结构进行编码的格式，基于Javascript对象表示法
  //(JavaScript Object Notation, 简称JSON)的地理空间信息数据交换格式。
  // GeoJSON对象可以表示几何、特征或者特征集合。
  //GeoJSON支持下面几何类型：点、线、面、多点、多线、多面和几何集合
  var neighborhoodsPromise = Cesium.GeoJsonDataSource.load(
    "./assets/SampleData/sampleNeighborhoods.geojson"
  );

  // 保存邻域数据的新实体集合
  var neighborhoods;
  //配置地标文件
  var kmlOptions = {
    camera: viewer.scene.camera,
    canvas: viewer.scene.canvas,
    // 如果我们想要将几何特征（多边形、线串和线性环）固定在地面上，则为 true。
    clampToGround: true,
  };
  //KML文件是谷歌公司创建的一种地标性文件。
  //用于记录某一地点、或连续地点的时间、经度、纬度、海拔等地理信息数据，供GE等有关软件使用。
  // Load geocache points of interest from a KML file
  // Data from : http://catalog.opendata.city/dataset/pediacities-nyc-neighborhoods/resource/91778048-3c58-449c-a3f9-365ed203e914
  var geocachePromise = Cesium.KmlDataSource.load(
    "./assets/SampleData/sampleGeocacheLocations.kml",
    kmlOptions
  );
  //将geocache广告牌实体添加到场景中并为其设置样式
  geocachePromise.then((dataSource) => {
    // 将新数据作为实体添加到查看器
    viewer.dataSources.add(dataSource);

    // 获取实体数组
    var geocacheEntities = dataSource.entities.values;

    for (var i = 0; i < geocacheEntities.length; i++) {
      var entity = geocacheEntities[i];
      if (Cesium.defined(entity.billboard)) {
        // 调整垂直原点，使图标位于地形上
        entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
        // 可以改变图标样式
        entity.billboard.image = "/assets/tagpark.png";
        // 禁用标签以减少混乱
        entity.label = undefined;
        // 添加距离显示条件
        entity.billboard.distanceDisplayCondition =
          new Cesium.DistanceDisplayCondition(10.0, 20000.0);
        // 以度为单位计算纬度和经度,获取这个实体的具体位置
        var cartographicPosition = Cesium.Cartographic.fromCartesian(
          entity.position.getValue(Cesium.JulianDate.now())
        );
        var latitude = Cesium.Math.toDegrees(cartographicPosition.latitude);
        var longitude = Cesium.Math.toDegrees(cartographicPosition.longitude);
        console.log('longitude', longitude);
        // 修改描述，点击图标的时候显示的一些信息
        var description =
          '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' +
          "<tr><th>" +
          "Longitude" +
          "</th><td>" +
          longitude.toFixed(5) +
          "</td></tr>" +
          "<tr><th>" +
          "Latitude" +
          "</th><td>" +
          latitude.toFixed(5) +
          "</td></tr>" +
          "<tr><th>" +
          "实时人流" +
          "</th><td>" +
          Math.floor(Math.random() * 20000) +
          "</td></tr>" +
          "<tr><th>" +
          "安全等级" +
          "</th><td>" +
          Math.floor(Math.random() * 5) +
          "</td></tr>" +
          "</tbody></table>";
        entity.description = description;
      }
    }
  });

  //当GeoJson文件加载成功后的操作
  neighborhoodsPromise.then((dataSource) => {
    // 将新数据作为实体添加到查看器
    viewer.dataSources.add(dataSource);

    //将实例保存到变量neighborhoods里
    neighborhoods = dataSource.entities;

    // 获取实例里的数据，是一个数组
    var neighborhoodEntities = dataSource.entities.values;

    //遍历这个数组以便对每一项进行样式配置，并且把这些数据放置到地形表面
    for (var i = 0; i < neighborhoodEntities.length; i++) {
      //每次循环到的数据都单独拿到
      var entity = neighborhoodEntities[i];

      //判断一下定义的多边形是否存在
      if (Cesium.defined(entity.polygon)) {
        // 使用kml邻域值作为实体名称
        entity.name = entity.properties.neighborhood;

        // 将多边形材质设置为随机的半透明颜色
        entity.polygon.material = Cesium.Color.fromRandom({
          red: 0.1,
          maximumGreen: 0.5,
          minimumBlue: 0.5,
          alpha: 0.6,
        });

        // 告诉多边形为地形着色。 ClassificationType.CESIUM_3D_TILE 将为 3D 图块集着色，而 ClassificationType.BOTH 将为 3d 图块和地形着色（BOTH 是默认值）
        entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN;

        // 生成多边形中心,意思就是设置这个多边形的位置
        var polyPositions = entity.polygon.hierarchy.getValue(
          Cesium.JulianDate.now()
        ).positions;

        // 上面生成中心点，这里进行配置中心点
        var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;

        // 设置在地球的表面
        polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
        entity.position = polyCenter;

        // 生成每个多边形的标签
        entity.label = {
          text: entity.name,
          showBackground: true,
          scale: 0.6,
          //标签水平的位置
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          //标签垂直的位置
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          //设置一下标签展示范围，摄像头高度
          distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
            10.0,
            8000.0
          ),
          //超过这个范围标签就不能被点击
          disableDepthTestDistance: 100.0,
        };
      }
    }
  });
});
// 当地标文件加载成功后，将实体添加到场景中并为其设置样式
</script>
 
<style>
#cesiumContainer {
  width: 1000px;
  height: 100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
}
</style>